package com.k8.cluster.clusterInvokerImpl;


import com.k8.rpc.cluster.loadBalance.LoadBalance;
import com.k8.rpc.invoke.Invoker;
import com.k8.rpc.invoke.invocation.Invocation;
import com.k8.rpc.result.Result;

/**
 * @Author: k8
 * @CreateTime: 2025-03-20
 * @Version: 1.0
 */
public class FailoverClusterInvoker<T> extends AbstractSessionSupportClusterInvoker<T> {
    private Class<T> type;
    private int retries;

    @Override
    public void setLoadBalance(LoadBalance<T> loadBalance) {
        super.setLoadBalance(loadBalance);
        this.retries = loadBalance.getSize();
    }


    @Override
    public Class<T> getInterface() {
        return this.type;
    }

    @Override
    public Result doInvoke(Invocation invocation) throws Throwable {
        return doInvoke0(invocation, 1);
    }

    public Result doInvoke0(Invocation invocation, int invokeNums) throws Throwable {
        Invoker<T> invoker = loadBalance.nextInvoker();
        Result result = null;
        try {
            result = invoker.invoke(invocation);
        } catch (Throwable throwable) {
            if (invokeNums < retries) {
                result = doInvoke0(invocation, invokeNums + 1);
            } else {
                throw throwable;
            }
        }
        return result;
    }

    @Override
    public void setInterface(Class<T> type) {
        this.type = type;
    }
}
